package com.sxkj.gis.wms.factory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.styling.SLDParser;
import org.geotools.styling.Style;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.xml.sax.InputSource;

import com.sxkj.gis.wms.bean.DoWmsParams;
import com.sxkj.gis.wms.bean.UrlBean;
import com.sxkj.gis.wms.bean.WmsParams;
import com.sxkj.gis.wms.comm.WmsLayersPath;

public class DoWmsParamsFactory implements WmsFactory {
	/**
	 * 获取data文件在项目中的路径
	 */
	public static String basePath = DoWmsParamsFactory.class.getClassLoader().getResource("data/").getPath();
	
	/**
	 * 返回DoWmsParams实体
	 * @throws IOException 
	 */
	@Override
	public DoWmsParams createDoWmsParamsGetMap(WmsParams wmsParams) throws IOException {
		DoWmsParams doWmsParams = null;
		//判断是否是WMS-getMap-SLD-BODY-LiteralMode.url.do 根据SLD_BODY属性是否有值
		if(wmsParams.getLayers()==null&&wmsParams.getStyles()==null&&wmsParams.getSLD_BODY()!=null){
			wmsParams.setLayers(getLayersBySLDBODY(wmsParams.getSLD_BODY()));
			wmsParams.setStyles(getSldNameBySLD_BODY(wmsParams.getSLD_BODY()));
			doWmsParams = new DoWmsParams(
										wmsParams.getVersion(),
										wmsParams.getRequest(),
										getBbox(wmsParams.getBbox()),
										getWidth(wmsParams.getWidth()),
										getHeight(wmsParams.getHeight()),
										getSimpleFeatureSources(wmsParams.getLayers()),
										getStylels(wmsParams.getStyles(),wmsParams.getSLD_BODY()),
										wmsParams.getFormat(),
										wmsParams.getSrs());
			return doWmsParams;
		}
		else{
			doWmsParams = new DoWmsParams(
										wmsParams.getVersion(),
										wmsParams.getRequest(),
										getBbox(wmsParams.getBbox()),
										getWidth(wmsParams.getWidth()),
										getHeight(wmsParams.getHeight()),
										getSimpleFeatureSources(wmsParams.getLayers()),
										getStylels(wmsParams.getStyles(),wmsParams.getSLD_BODY()),
										wmsParams.getFormat(),
										wmsParams.getSrs());
		}
		return doWmsParams;
	}
	
	/**
	 *  返回WmsParams实体
	 */
	@Override
	public WmsParams createWmsParams(UrlBean urlBean) {
		// TODO Auto-generated method stub
		Map<String,Object> paramsMap = xmlElements(urlBean.getBody());
		//SLD_BODY为null
		paramsMap.put("SLD_BODY", null);
		List<Object> bbox = (List<Object>) paramsMap.get("bbox");
		String Bbox ="";
		for(int i=0;i<bbox.size();i++){
			if(i==bbox.size()-1){
				Bbox=Bbox+bbox.get(i);
			}else{
				Bbox=Bbox+bbox.get(i)+",";
			}
		}
		WmsParams wmsParams = new WmsParams(
											(String)paramsMap.get("version"),
											(String)paramsMap.get("request"),
											(String)paramsMap.get("layers"),
											(String)paramsMap.get("styles"),
											(String)paramsMap.get("srs"),
											Bbox,
											(String)paramsMap.get("width"),
											(String)paramsMap.get("height"),
											(String)paramsMap.get("Format"),
											(String)paramsMap.get("SLD_BODY")
											);
		return wmsParams;
	}
	
	/**
	 * GetFeatureInfo请求 解析WmsParams 中属性参数  通过构造方法创建实体类DoWmsParams
	 */
	@Override
	public DoWmsParams createDoWmsParamsGetFeatureInfo(WmsParams wmsParams) {
		// TODO Auto-generated method stub
		DoWmsParams doWmsParams = new DoWmsParams(
												wmsParams.getVersion(),
												wmsParams.getRequest(),
												getBbox(wmsParams.getBbox()),
												getWidth(wmsParams.getWidth()),
												getHeight(wmsParams.getHeight()),
												getSimpleFeatureSources(wmsParams.getLayers()),
												getStylels(wmsParams.getStyles(),wmsParams.getSLD_BODY()),
												wmsParams.getFormat(),
												wmsParams.getSrs(),
												wmsParams.getInfo_format(),
												getX(wmsParams.getX()),
												getY(wmsParams.getY()),
												getSimpleFeatureSources(wmsParams.getQuery_layers()));
		
		return doWmsParams;
	}
	
	/**
	 * 处理GetMapParams 中String 类型 layers 转换为 SimpleFeatureSource样式的list集合返回
	 * @return
	 */
	public static List<SimpleFeatureSource> getSimpleFeatureSources(String layers){
		List<SimpleFeatureSource> sfsList = new ArrayList<>();
		try{
			String[] layersString = layers.split(",");
			String[] layersNameString =new String[layersString.length];
			for(int i=0;i<layersString.length;i++){
				layersNameString[i]=layersString[i].split(":")[1];
				for(int j=0;j<WmsLayersPath.getWmsLayersPath().size();j++){
					if(WmsLayersPath.getWmsLayersPath().containsKey(layersNameString[i])){
						String ShpPath = basePath + WmsLayersPath.getWmsLayersPath().get(layersNameString[i]);
						FileDataStore store = FileDataStoreFinder.getDataStore(new File(ShpPath));
						SimpleFeatureSource featureSource = store.getFeatureSource();
						
						sfsList.add(featureSource);
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return sfsList;
	}
	
	/**
	 * 处理WmsParams 中String 类型 styles 转换为 Style样式的list集合返回
	 * @param styles
	 * @return
	 */
	public static List<Style> getStylels(String styles,String SLD_BODY ){
		List<Style> styleList = new ArrayList<>();
		if(SLD_BODY!=null){
			styleList.add(getStyle(styles));
			return styleList;
		}
		else{
			String[] stylesString = styles.split(",");
			for(int i=0;i<stylesString.length;i++){
				//集合styleList中添加获取到的样式
				styleList.add(getStyle(getSldPath(stylesString[i])));
			}
			return styleList;
		}
	}
	
	/**
	 * 根据WmsParams 中的styles 对应的字段  通过解析字段对应的xml 来获取每个字段对应的sld文件对应的文件名
	 * @return
	 */
	public static String getSldPath(String styleName){
		String styleNameXmlPath = basePath+"styles/"+styleName+".xml"; 
		SAXBuilder saxBuilder = new SAXBuilder();
		String sldXmlName = null;
		InputStream in = null;
		try{
			in = new FileInputStream(styleNameXmlPath);
			InputStreamReader isr = new InputStreamReader(in);
			Document document = saxBuilder.build(isr);
			Element rootElement = document.getRootElement();
			List<Element> ele = rootElement.getChildren();
			for(Element e:ele){
				if(e.getName().equals("filename")){
					sldXmlName = e.getValue();
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return sldXmlName;
	}
	
	/**
	 * 根据getSldPath(String styleName) 方法返回值 -->sldXmlName 经过处理返回Style
	 * @return
	 */
	public static Style getStyle(String sldXmlName){
		String sldXmlPath = basePath+ "styles/"+sldXmlName;
		org.geotools.styling.Style style =null;
		try{
			org.geotools.styling.StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();
			File sldFile = new File(sldXmlPath);
			
			SLDParser stylereader = new SLDParser(styleFactory,sldFile.toURI().toURL());
			org.geotools.styling.Style[] stylearray = stylereader.readXML();
			style= stylearray[0];
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return style;
	}
	
	/**
	 * 处理WmsParams 中 String 类型 height 转换为 Integer类型
	 * @param height
	 * @return
	 */
	public static Integer getHeight(String height){
		return Integer.parseInt(height);
	}
	
	/**
	 * 处理GetMapParams 中 String 类型 width 转换为 Integer类型
	 * @param width
	 * @return
	 */
	public static Integer getWidth(String width){
		return Integer.parseInt(width);
	}
	
	/**
	 * 处理GetMapParams 中 String 类型 x 转换为 Integer类型
	 * @param x
	 * @return
	 */
	public static Integer getX(String x){
		return Integer.parseInt(x);
	}
	
	/**
	 * 处理GetMapParams 中 String 类型 y 转换为 Integer类型
	 * @param y
	 * @return
	 */
	public static Integer getY(String y){
		return Integer.parseInt(y);
	}
	
	/**
	 * 处理WmsParams 中 String 类型 bbox 转换为 Double[]类型
	 * @param bbox
	 * @return
	 */
	public static Double[] getBbox(String bbox){
		String[] srsStrings = bbox.split(",");
		Double[] srsDouble = new Double[srsStrings.length];
		for(int i =0;i<srsStrings.length;i++){
			srsDouble[i]=Double.parseDouble(srsStrings[i]);
		}
		return srsDouble;
	}
	
	
	/**
	 * 解析getMapXML
	 * @param getMapXML
	 * @return
	 */
	public static Map<String,Object> xmlElements(String getMapXML){
		Map<String,Object> paramsList = new HashMap<>();
		
		List<Object> coords = new ArrayList<>();
		//创建一个新的字符串
		StringReader read = new StringReader(getMapXML);
		
		//创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
		InputSource source = new InputSource(read);
		
		//创建一个新的SAXBuilder
		SAXBuilder sb = new SAXBuilder();
		
		try{
			Document doc = sb.build(source);
			
			//获取根节点
			Element root = doc.getRootElement();
			if(root.getName().equals("ogc:GetMap")){
				paramsList.put("request", root.getName().split(":")[1]);
				paramsList.put("version", root.getAttribute("version"));
			}
			//获取根节点下的子节点
			List<Element> rootChilds = root.getChildren();
			
			for(Element rootChild:rootChilds){
				if(rootChild.getName().equals("BoundingBox")){
					String[] srs1 = rootChild.getAttributeValue("srsName").split("#");
					String srs2 = srs1[srs1.length-1];
					String[] srs3 = rootChild.getAttributeValue("srsName").split("srs/");
					String srs4 = (srs3[srs3.length-1]).split(".xml")[0];
					String srs5 = srs4.toUpperCase()+":"+srs2;
					paramsList.put("srs", srs5);
				}
					List<Element> rootChildToChilds = rootChild.getChildren();
					
					for(Element rootChildToChild:rootChildToChilds){
						if(rootChildToChild.getName().equals("Format")){
							paramsList.put("Format", rootChildToChild.getValue());
						}
						List<Element> rootChildToChildToChilds = rootChildToChild.getChildren();
						for(Element rootChildToChildToChild:rootChildToChildToChilds){
							if(rootChildToChildToChild.getName().equals("Name")){
								paramsList.put("layers", rootChildToChildToChild.getValue());
							}
							if(rootChildToChildToChild.getName().equals("X")){
								coords.add(rootChildToChildToChild.getValue());
								rootChildToChildToChild.getValue();
							}
							if(rootChildToChildToChild.getName().equals("Y")){
								coords.add(rootChildToChildToChild.getValue());
								rootChildToChildToChild.getValue();
							}
							if(rootChildToChildToChild.getName().equals("Width")){
								paramsList.put("width", rootChildToChildToChild.getValue());
							}
							if(rootChildToChildToChild.getName().equals("Height")){
								paramsList.put("height", rootChildToChildToChild.getValue());
							}
							List<Element> rootChildToChildToChildToChilds = rootChildToChildToChild.getChildren();
							
							for(Element rootChildToChildToChildToChild:rootChildToChildToChildToChilds){
								if(rootChildToChildToChildToChild.getName().equals("Name")){
									paramsList.put("styles", rootChildToChildToChildToChild.getValue());
								}
							}
						}
					}
				
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		paramsList.put("bbox",coords);
		return paramsList;
	}
	
	/**
	 * 解析WMS_getMap_SLD_BODY_LiteralMode-1.3.url 请求中SLD_BODY
	 * @param SLD_BODY
	 * @return
	 */
	public static String getLayersBySLDBODY(String SLD_BODY){
		List<String> layersList = new ArrayList<>();
		//创建一个新的字符串
		StringReader read = new StringReader(SLD_BODY);
		//创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
		InputSource source = new InputSource(read);
		//创建一个新的SAXBuilder
		SAXBuilder sb = new SAXBuilder();
		try{
			Document doc = sb.build(source);
			Element root = doc.getRootElement();
			List<Element> rootChilds = root.getChildren();
			for(Element rootChild:rootChilds){
				List<Element> rootChildsToChilds = rootChild.getChildren();
				for(Element rootChildsToChild:rootChildsToChilds){
					if(rootChildsToChild.getName().equals("Name")){
						layersList.add(rootChildsToChild.getValue());
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		String layers = "";
		for(int i=0;i<layersList.size();i++){
			if(i==layersList.size()-1){
				layers+=layersList.get(i);
				
			}else{
				layers+=layersList.get(i)+",";
			}
		}
		System.out.println("SLD_BODY解析出layerName :"+layers);
		return layers;
	}
	
	/**
	 * WMS_getMap_SLD_BODY_LiteralMode-1.3.url 请求中SLD_BODY 并转换为一个sld文件保存到项目路径中
	 * @param SLD_BODY
	 * @return
	 * @throws IOException 
	 */
	public static String getSldNameBySLD_BODY(String SLD_BODY) throws IOException{
		String sldName = "SLD_BODY.sld";
		byte[] sldByte = SLD_BODY.getBytes();
		
		FileOutputStream out = new FileOutputStream(basePath+"styles\\"+sldName);
		out.write(sldByte);
		out.flush();
		out.close();
		return sldName;
	}

	
}
